
/*
 * parser_utf8.c
 *
 * Functions to decode a utf-8 stream to UCS-4
 *
 * 26.05.2010, Klaus Hennemann
 */

#include <string.h>
#include "utf8.h"


void utf8_init (struct UTF8 *utf8)
{
        memset(utf8, 0, sizeof(*utf8));
}


/*
 * This UTF-8 decoder follows RFC-3629. Please see the RFC for
 * more informations.
 *
 */
int utf8_decode (struct UTF8 *utf8, unsigned char in, uint32_t *out)
{
        /* is the input byte a single byte charater? */
        if ( !(in & 0x80) ) {
                utf8->cont_left = 0;
                *out = in;
                return 1;
        }

        /* is the input an UTF-8 cont byte? */
        if ( (in & 0xc0) == 0x80 ) {
                if (utf8->cont_left > 0) {
                        utf8->uc <<= 6;
                        utf8->uc |= in & 0x3f;

                        if (--utf8->cont_left == 0) {
                                *out = utf8->uc;
                                return 1;
                        }
                }

                return 0;
        }

        /* 110xxxxx 10xxxxxx */
        if (in >= 0xc2 && in <= 0xdf) {
                utf8->uc = in & 0x1f;
                utf8->cont_left = 1;
                return 0;
        }

        /* 1110xxxx 10xxxxxx 10xxxxxx */
        if (in >= 0xe0 && in <= 0xef) {
                utf8->uc = in & 0x0f;
                utf8->cont_left = 2;
                return 0;
        }

        /* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
        if (in >= 0xf0 && in <= 0xf4) {
                utf8->uc = in & 0x07;
                utf8->cont_left = 3;
                return 0;
        }

        /* obviously we found an invalid UTF-8 encoding. So
           we return the error character U+00BF */
        utf8->cont_left = 0;
        *out = 0xbf;
        return 1;
}


